﻿#include "bmfont.h"

namespace ifire::ui {

// 默认的项目，表示空白
static BMFontChar EMPTY_CHAR;

BMFontChar::BMFontChar()
    : id(-1)
    , x(0)
    , y(0)
    , width(0)
    , height(0)
    , xoffset(0)
    , yoffset(0)
    , xadvance(0)
    , page(0)
    , chnl(0)
    , uv_point(0.0f, 0.0f)
    , uv_size(0.0f, 0.0f) {}

BMFontChar::BMFontChar(const ikit::XmlNode& node, int index) {
  id = node("id");
  x = node("x");
  y = node("y");
  width = node("width");
  height = node("height");
  xoffset = node("xoffset");
  yoffset = node("yoffset");
  xadvance = node("xadvance");
  page = node("page");
  chnl = node("chnl");
}
BMFontPage::BMFontPage(const XmlNode& node, int index) {
  id = node("id");
  file = node("file");
}
BMFontInfo::BMFontInfo(const XmlNode& node) {
  face = node("face");
  size = node("size");
  bold = node("bold");
  italic = node("italic");
  charset = node("charset");
  unicode = node("unicode");
  stretchH = node("stretchH");
  smooth = node("smooth");
  aa = node("aa");
  padding = node("padding");
  spacing = node("spacing");
  outline = node("outline");
}
BMFontCommon::BMFontCommon(const XmlNode& node) {
  lineHeight = node("lineHeight");
  base = node("base");
  scaleW = node("scaleW");
  scaleH = node("scaleH");
  pages = node("pages");
  packed = node("packed");
  alphaChnl = node("alphaChnl");
  redChnl = node("redChnl");
  greenChnl = node("greenChnl");
  blueChnl = node("blueChnl");
}
BMFont::BMFont(const std::string_view& filename) { Load(filename); }

void BMFont::Load(const std::string_view& filename) {
  XmlReader reader(filename.data());
  mCommon = BMFontCommon(reader["common"]);
  mInfo = BMFontInfo(reader["info"]);

  mPages = XmlNode_ReadItems<BMFontPage>(reader["pages"], "page");
  mChars = XmlNode_ReadItems<BMFontChar>(reader["chars"], "char");

  // 计算出贴图的大小（不用每次都转化）
  mSize = SizeF(
      static_cast<float>(mCommon.scaleW), static_cast<float>(mCommon.scaleH));

  // 计算每个Char的UV坐标
  for (auto& c : mChars) {

    // 这里有个+1的操作。也许是因为Padding的原因。导致如果给这个项目+1，才能显示完字符。
    // 否则字符串看上去像是右边被削去了一点。
    float width = static_cast<float>(c.width + 1) / mSize.width;
    float height = static_cast<float>(c.height) / mSize.height;
    c.uv_size = XMFLOAT2(width, height);

    float u = static_cast<float>(c.x) / mSize.width;
    // 因为载入的项目是反的，所以需要这样一个1.0f减去原位置，再减去高度的修正。
    float v = 1.0f - static_cast<float>(c.y) / mSize.height - height;
    c.uv_point = XMFLOAT2(u, v);

    //KLOG("%c, u:%.4f, v:%.4f, width:%.4f, height:%.4f, ", static_cast<char>(c.id), u, v, width, height);
  }
}
const BMFontChar& BMFont::GetChar(int id) const {
  for (auto& c_info : mChars) {
    if (c_info.id == id) {
      return c_info;
    }
  }
  return EMPTY_CHAR;
}
} // namespace ifire
